﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;

namespace BasicMVVMCommand
{
    class INPCManager : WeakEventManagerBase<INPCManager, INotifyPropertyChanged>
    {
        protected override void StartListeningTo(INotifyPropertyChanged source)
        {
            source.PropertyChanged += DeliverEvent;
        }

        protected override void StopListeningTo(INotifyPropertyChanged source)
        {
            source.PropertyChanged -= DeliverEvent;
        }
    }

    class GenericListener : IWeakEventListener
    {
        Dictionary<Type, EventHandler> dispatchMap = new Dictionary<Type, EventHandler>();

        public void DeRegisterListener(Type managerType, EventHandler eventHandler)
        {
            dispatchMap.Remove(managerType);  
        }

        public void RegisterListener(Type managerType, EventHandler eventHandler)
        {
            dispatchMap[managerType] = eventHandler;
        }

        public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
        {
            EventHandler handler = dispatchMap[managerType];
            if (handler != null)
            {
                handler(sender, e);
                return true;
            }
            return false;
        }
    }

    public abstract class WeakEventManagerBase<T, TSource> : WeakEventManager
        where T : WeakEventManagerBase<T, TSource>, new()
        where TSource : class
    {
        public static T Current
        {
            get
            {
                Type managerType = typeof(T);
                T manager = WeakEventManager.GetCurrentManager(managerType) as T;
                if (manager == null)
                {
                    manager = new T();
                    WeakEventManager.SetCurrentManager(managerType, manager);
                }
                return manager;
            }
        }

        public static void AddListener(TSource source, IWeakEventListener listener)
        {
            Current.ProtectedAddListener(source, listener);
        }

        public static void RemoveListener(TSource source, IWeakEventListener listener)
        {
            Current.ProtectedRemoveListener(source, listener);
        }

        protected override sealed void StartListening(object source)
        {
            StartListeningTo(source as TSource);
        }

        protected abstract void StartListeningTo(TSource source);

        protected override sealed void StopListening(object source)
        {
            StopListeningTo(source as TSource);
        }

        protected abstract void StopListeningTo(TSource source);
    }

}
